package hidra.qualityIndicator;

import java.util.ArrayList;
import java.util.List;

public class MonteCarloHypervolume {

	
 hidra.qualityIndicator.util.MetricsUtil utils_;
	  
  /**
  * Constructor
  * Creates a new instance of MultiDelta
  */
  public MonteCarloHypervolume() {
    utils_ = new hidra.qualityIndicator.util.MetricsUtil();
  } // Hypervolume
  
  
  
  boolean  dominates(double  point1[], double  point2[], int  noObjectives) {
	    int  i;
	    int  betterInAnyObjective;

	    betterInAnyObjective = 0;
	    for (i = 0; i < noObjectives && point1[i] <= point2[i]; i++)
	      if (point1[i] < point2[i])
		betterInAnyObjective = 1;
	    
	    return ((i >= noObjectives) && (betterInAnyObjective>0));
  } //Dominates
  
  
  
  
  public double hypervolume(double [][] paretoFront,  double [] referencePoint, int numberOfObjectives, int numberOfPoints) {
				  
	  List<double[]> normalizedPoints = new ArrayList<double[]>();
			
	  for(int i=0; i < paretoFront.length  ;i++){
		  
		  double[] point = new double[numberOfObjectives];
		  boolean include = true;
		  
		  for(int j=0;   j < numberOfObjectives  ;  j++){
			  
			  if( paretoFront[i][j] >  referencePoint[j]){
				  
				  point[j] = paretoFront[i][j] / referencePoint[j];
				  include = false;
			  }
			  
		  }
		  
		  if(include){
			  normalizedPoints.add(point);
		  }
		  
		  
	  }
	  	  
	  
	  double[][] randomPoints = new double[numberOfPoints][numberOfObjectives]; 
	  
	  
	  for(int i=0; i < randomPoints.length; i++){
		  
		  for(int j=0; j < numberOfObjectives;  j++){
			  
			  randomPoints[i][j] = Math.random();
			  
			  
		  }
	  }
	  
	  
	  boolean[] fDominated = new boolean[randomPoints.length];
	  
	  for(int i=0; i < paretoFront.length  ;i++){		  
		  		  		 
		  for(int j=0; j < randomPoints.length; j++){			  			  
			  
			  
			  if(dominates(paretoFront[i], randomPoints[j], numberOfObjectives)){
				  fDominated[j] = true;
			  }
			  
		  }
		  
	  }
	  
	  double sum  = 0.0;
	  
	  for(int j=0; j < randomPoints.length; j++){		
		  
		  if(fDominated[j]){
			  sum += 1;
		  }
		  
	  }
	  
	  double value = sum / randomPoints.length;
	  
	  return value;
  }
  
  
  
  
	
  
  
}
